Checking for Well-Formedness
What is the best (and easiest) way to make sure that your documents are well-formed?  There are a number of tools that are available that you can use to check your documents.  Best of all, many of the good ones are free!  These tools are called non-validating parsers (validation is a whole separate topic we are working towards) and they check your XML syntax.  Non-validating parsers are like the old “lint” tool that C/C++ programmers use to pick out the not-so-obvious errors in their source code. 
 
A simple (and free) tool for checking for well-formedness is the Microsoft XML Notepad.  Do not use Microsoft Internet Explorer to check your XML documents!  Internet Explorer is a browser and by its nature is extremely lenient.  On the other hand, XML Notepad provides strict well-formedness checking.  

Tip:	XML Notepad can be downloaded for free off the Microsoft web site at  http://msdn.microsoft.com/xml/notepad/download.asp.   This does not mean that it is the best.  It just well works for our example.

Unlike many of the non-validating parsers out there, XML Notepad uses a graphical user interface.  Most of these tools use a command-line interface.  Based on your preferences, you can choose the set of tools that you will add to your XML developers toolkit.  Many of them even come with source code so that you can modify them to your liking.

Using XML Notepad

Let’s walk through a document that has errors and check it for well-formedness using XML Notepad.  This is going to be familiar to software developers who are used to using compilers to catch errors in their source code.

The following is the contents of our flawed document.  The lines in bold contain the errors.  See if you can identify what the errors are before we use XML Notepad to identify them for us.

<?xml version="1.0"?>
<!DOCTYPE employes [
	<!ELEMENT employees ( employee+ )>

	<!ELEMENT employee (name position, address, phone)>
	<!ATTLIST employee id ID>

	<!ELEMENT name (first, last)>
	<!ELEMENT first (#PCDATA)>
	<!ELEMENT last  (#PCDATA)>

	<!ELEMENT position (#PCDATA)>

	<!ELEMENT address (street?, city?, state?, zip?)>
	<!ELEMENT street (#PCDATA)>
	<!ELEMENT city   (#PCDATA)>
	<!ELEMENT state  (#PCDATA)>
	<!ELEMENT zip    (#PCDATA)>

	<!ELEMENT phone (main, office*, fax*, mobile*, home*)>
	<!ELEMENT main   (#PCDATA)>
	<!ELEMENT office (#PCDATA)>
	<!ELEMENT fax    (#PCDATA)>
	<!ELEMENT mobile (#PCDATA)>
	<!ELEMENT home   (#PCDATA)>
]>

<employees>

    <employee id=A1234>
        <name>
            <first>John</first>
            <last>Doe</last>
        </name>
        <position>Programmer</position>
        <address>
            <street>123 Main Street</street>
            <city>Anywhere</city>
            <state>CA</state>
            <zip>92000</zip>
        </address>
        <phone>
            <main>(714) 555-1000</main>
            <fax>(714) 555-1001</fax>
        </phone>
    </employee>

    <employee id="A2345">
        <name>
            <first>Jane</first>
            <last>Doe</last>
        </name>
        <position>Systems Analyst</position>
        <address>
        </address>
        <phone>
            <main>(714) 555-2000<main>
            <mobile>(949) 555-2200</mobile>
            <home>(949) 555-2220</home>
        </phone>
    </employee>
</employees>

File: Chapter 5\Employees_NotWellFormed.xml

Let’s open the document in XML Notepad and see how it processes the errors.  Like most non-validating parsers, it only reports one error at a time.  Do not expect these tools to work like a compiler (e.g. C++, Java, etc.), which gives you a list of errors and/or warnings.  This is more of a nuisance than anything, but it does take time to get through a complex document.  

Tip:	It is often a good idea to check for well-formedness throughout the development of your document instead of creating the entire document then running it through a parser.

When we attempt to open the document the for first time, the error that we get is:

Error 1: Line 5 – missing comma (syntax error).

The first error is not entirely obvious, and this is not uncommon when working with XML parsers.  The real error is that there is a comma ( , ) missing between the “name” and “position” declarations.  The parser ran into the error and could not determine how to parse it, so it put us on the first position it could not understand.

 To fix the error, we need to change line 5 by adding a comma between “name” and “position”.

<!ELEMENT employee (name, position, address, phone)>

Let’s reload the document and get the next error.

Error #2: Line 6 – missing #REQUIRED declaration (syntax error).

Now this one is somewhat ridiculous.  The actual error is that the #REQUIRED attribute is missing.  In this example, the error message is not even close to the actual error.  However, in XML Notepad’s defense, when this same error is run through several other parsers, you get almost the exact same error.

The fix is to add the #REQUIRED attribute to the declaration because ID attributes are required.

<!ATTLIST employee id ID #REQUIRED>

The next error message is much more descriptive.

Error #3: Line 28 – the root element is named differently than the name specified in the <!DOCTYPE> tag (syntax error).

The full error message reads: “The name of the top most element must match the name of the DOCTYPE declaration.”
  
To fix this error, we need to match the name specified in the <!DOCTYPE> tag to the name of the root element.  

<!DOCTYPE employes [

. . . (omitted)

<employees>

In this case, we have misspelled the name in the <!DOCTYPE> tag.  We can correct the error by fixing the typo.

<!DOCTYPE employees [

Let’s reload the document and try again.  The next error that we encounter will be in the document content.  However, this error is still regarding the well-formedness of the document, and is not a violation of a declaration.

Error #4: Line 30 – missing quotes around the value assigned to the id attribute.

The full error message reads: “A string literal was expected, but no opening quote character was found.”

This is indeed a syntax error.  All string literals assigned as values to attributes need to be enclosed in quotes.  To fix the error, we need to add some quotes.

<employee id="A1234">

The final error that XML Notepad finds is going to be a bit tricky.  The reason being that the error message that we get is not going to give us much of a clue as to what the real error is.  This is because XML Notepad attempts to do validity checking as well as checking for well-formedness.  This being the case, it is going to report a validity error to us, which it is, but it is due to a lack of well-formedness in the document.
 
Error #5: Line 57 – missing terminator tag </main> (syntax error).

The error we received is in fact correct, event though the real error is that the terminator tag for <main> is missing.  The XML processor is returning a content error to us.  Here is how the XML processor came to this conclusion:

The <main> element is declared as type #PCDATA.  These means that it can only contain text data.  It cannot contain any other elements.  This is the rule defined in the DTD.

The <main> element is a required element that can only appear once within a <phone> element.  This is the way that  it is declared within the <phone> element’s declaration. The XML processor found the text data immediately following the greater-than symbol (>) in the open tag and started to process the text.

The XML processor encountered another <main> element tag.  This is a typo; the termination backslash (/) is missing.  To the XML processor, however, this was another <main> element.  This violates both rules defined previously.  Namely, <main> can only appear once and it can only have text data.

This is why we got a content error, and not a syntax error.  When you run this example through a purely non-validating parser, which XML Notepad is not, a syntax error is generated regarding the missing terminator tag.

Tips:	It is often a good idea to have multiple parsers that you can use during this process.  This is very helpful when one parser gives you a less than helpful error message or when you are having trouble understanding what the real error is.

Another tip is to use a separate non-validating parser from your validating parser.  This way you can check for well-formedness apart from checking for validity.  The last error we encountered is a good example of why it is often good to separate the two.